#include "DmMainAfx.h"
#include "Blend.h"

#include <xmmintrin.h>

BOOL xRender::BlendSrc32SSE(PBITMAP lpbDst, PBITMAPEX lpbSrc)
{
    LPBYTE lpScanSrc = (LPBYTE)lpbSrc->bmBits;
    LPBYTE lpScanDst = (LPBYTE)lpbDst->bmBits;
    DWORD width = lpbDst->bmWidth;
    for (int j = lpbDst->bmHeight; j > 0; --j)
    {
        LPDWORD lpPixelSrc = (LPDWORD)lpScanSrc;
        LPDWORD lpPixelDst = (LPDWORD)lpScanDst;
        int i = width >> 4;
        while (i--)
        {
            _mm_prefetch((char*)(lpPixelSrc) + 512, _MM_HINT_NTA);
            __m64 m0 = *(__m64*)lpPixelSrc;
            __m64 m1 = *(__m64*)(lpPixelSrc + 2);
            __m64 m2 = *(__m64*)(lpPixelSrc + 4);
            __m64 m3 = *(__m64*)(lpPixelSrc + 6);
            _mm_stream_pi((__m64*)lpPixelDst, m0);
            _mm_stream_pi((__m64*)(lpPixelDst + 2), m1);
            _mm_stream_pi((__m64*)(lpPixelDst + 4), m2);
            _mm_stream_pi((__m64*)(lpPixelDst + 6), m3);
            __m64 m4 = *(__m64*)(lpPixelSrc + 8);
            __m64 m5 = *(__m64*)(lpPixelSrc + 10);
            __m64 m6 = *(__m64*)(lpPixelSrc + 12);
            __m64 m7 = *(__m64*)(lpPixelSrc + 14);
            _mm_stream_pi((__m64*)(lpPixelDst + 8), m4);
            _mm_stream_pi((__m64*)(lpPixelDst + 10), m5);
            _mm_stream_pi((__m64*)(lpPixelDst + 12), m6);
            _mm_stream_pi((__m64*)(lpPixelDst + 14), m7);
            lpPixelSrc += 16;
            lpPixelDst += 16;
        }
        i = width & 15;
        while (i--)
        {
            *lpPixelDst = *lpPixelSrc;
        }
        lpScanSrc += lpbSrc->bmWidthBytes;
        lpScanDst += lpbDst->bmWidthBytes;
    }
    _mm_sfence();
    _m_empty();
    return TRUE;
}

BOOL xRender::BlendSrc32SSE2(PBITMAP lpbDst, PBITMAPEX lpbSrc)
{
    LPBYTE lpScanSrc = (LPBYTE)lpbSrc->bmBits;
    LPBYTE lpScanDst = (LPBYTE)lpbDst->bmBits;
    DWORD width = lpbDst->bmWidth;
    for (int j = lpbDst->bmHeight; j > 0; --j)
    {
        memcpy(lpScanDst, lpScanSrc, lpbDst->bmWidth * 4);
        lpScanSrc += lpbSrc->bmWidthBytes;
        lpScanDst += lpbDst->bmWidthBytes;
    }
    return TRUE;
}